#include "UdpServer.hpp"
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Thread.hpp"

using namespace ThreadMoudle;

int InitClient()
{
    int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        std::cerr << "create socket eror\n"
                  << std::endl;
        exit(1);
    }
    return sockfd;
}

void RecvMessage(int sockfd, const std::string &name)
{
    while (true)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        char buffer[1024];
        int n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
        if (n > 0)
        {
            buffer[n] = 0;
            std::cerr << buffer << std::endl;
        }
        else
        {
            std::cerr << "recvfrom error" << std::endl;
            break;
        }
    }
}

void SendMessage(int sockfd, std::string serverip, uint16_t severport, const std::string &name)
{
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(severport); // 转换重要！！！
    server.sin_addr.s_addr = inet_addr(serverip.c_str());

    std::string cli_profix = name + "# "; // sender-thread#
    while (true)
    {
        std::string line;
        std::cout << cli_profix;
        std::getline(std::cin, line);
        // 发消息，你要知道发送给谁
        int n = sendto(sockfd, line.c_str(), line.size(), 0, (struct sockaddr *)&server, sizeof(server));
        if (n <= 0)
            break;
    }
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cerr << "Usage: " << argv[0] << " server-ip server-port" << std::endl;
        exit(0);
    }
    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);
    int sockfd = InitClient();

    Thread recver("recver-thread", std::bind(&RecvMessage, sockfd, std::placeholders::_1));
    Thread sender("sender-thread", std::bind(&SendMessage, sockfd, serverip, serverport, std::placeholders::_1));

    recver.Start();
    sender.Start();

    recver.Join();
    sender.Join();

    ::close(sockfd);
    return 0;
}

// 单进程单线程版本(有问题！！！)
// 客户端在未来一定要知道服务器的IP地址和端口号
// .udp_client server-ip server-port
// .udp_client 127.0.0.1 8888
// int main(int argc, char *argv[])
// {
//     if (argc != 3)
//     {
//         std::cerr << "Usage: " << argv[0] << " server-ip server-port" << std::endl;
//         exit(0);
//     }

//     // 0.读取接收端IP和端口
//     std::string serverip = argv[1];
//     uint16_t serverport = std::stoi(argv[2]);

//     // 1.创建套接字
//     int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
//     if (sockfd < 0)
//     {
//         std::cerr << "create socket eror\n"
//                   << std::endl;
//         exit(1);
//     }

//     // 2.设置接收端信息
//     struct sockaddr_in server;
//     memset(&server, 0, sizeof(server));
//     server.sin_family = AF_INET;
//     server.sin_port = htons(serverport); // 转换重要！！！
//     server.sin_addr.s_addr = inet_addr(serverip.c_str());

//     // 3.发消息和接收消息
//     while (true)
//     {
//         std::string line;
//         std::cout << "Please Enter# ";
//         std::getline(std::cin, line); // 以行读取消息
//         // 发消息，你要知道发送给谁
//         int n = sendto(sockfd, line.c_str(), line.size(), 0, (struct sockaddr *)&server, sizeof(server));
//         if (n > 0)
//         {
//             // 收消息
//             struct sockaddr_in temp;
//             socklen_t len = sizeof(temp);
//             char buffer[1024];
//             int m = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&temp, &len);
//             if (m > 0)
//             {
//                 buffer[m] = 0;
//                 std::cout << buffer << std::endl;
//             }
//             else
//             {
//                 break;
//             }
//         }
//         else
//         {
//             break;
//         }
//     }

//     // 4.关闭套接字
//     ::close(sockfd);
//     return 0;
// }